home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
pc
/
files
/
t_sys5
/
unixkit.tgz
/
unixkit.tar
/
unixkit
/
common
/
bsd_tun.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-05
|
6KB
|
219 lines
/* This is a very early release of a Tunnel driver for 4.3 BSD systems.
* You need to run this program as root. Please think about security
* during shell escapes, ftp-sessions etc.
* Define PACKET in config.h to use this driver.
*
* On your UNIX system, you will have to issue the following command
* to activate the tunnel interface:
* ifconfig tun0 <unix-hostname> <nos-hostname>
*
* A corrected version of the Tunnel driver is available with ftp
* from sics.se.
*
* SM0RGV
*
* KA9WSB - argv[3] is now used to select the tunnel device number...
* this allows easier debug!
*
* KA9WSB - code added to reset the user id immediately after attaching
* the device. This allows us to run NOS as a setuid program, and have
* it relinquish root privs as soon as it no longer needs them!
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/stropts.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include "if_tnreg.h"
#include "global.h"
#include "config.h"
#include "mbuf.h"
#include "iface.h"
#include "netuser.h"
#include "slip.h"
#include "pktdrvr.h"
#include "asy.h"
struct tundrvr Tundrvr[TUN_MAX];
int tun_raw(),tun_stop();
void tun_input();
extern struct iface *Ifaces;
extern struct mbuf *Hopper;
extern char Nospace[];
int Ntun;
/* Define some NIT stuff to keep the compiler happy */
struct nitdrvr Nitdrvr[NIT_MAX];
int Nnit;
/* Attach a packet driver to the system
* argv[0]: hardware type, must be "packet"
* argv[1]: destination address
* argv[2]: interface label, same as real interface, e.g., "tun0"
* argv[3]: The tunnel device number; i.e. 0 == /dev/tun0, 1 == /dev/tun1
* argv[4]: maximum transmission unit, bytes, e.g., "1500"
* argv[5]: optional source IP address
*/
pk_attach(argc,argv,p)
int argc;
char **argv;
void *p;
{
struct ifreq ifr;
struct iface *if_tun;
struct tundrvr *pp;
char tundevice[16];
int i,val,if_flags;
if(Ntun >= TUN_MAX){
tprintf("Too many tunnel drivers\n");
return -1;
}
if(if_lookup(argv[2]) != NULLIF){
tprintf("Interface %s already exists\n",argv[2]);
return -1;
}
if_tun = (struct iface *)callocw(1,sizeof(struct iface));
if_tun->name = strdup(argv[2]);
if(argc > 5)
if_tun->addr = resolve(argv[5]);
else
if_tun->addr = Ip_addr;
if(if_tun->addr == 0){
tprintf(Noipaddr);
free((char *)if_tun);
return -1;
}
pp = &Tundrvr[Ntun];
if_tun->mtu = atoi(argv[4]);
if_tun->dev = Ntun;
setencap(if_tun,"None");
if_tun->raw = tun_raw;
if_tun->stop = tun_stop;
pp->iface = if_tun;
if_tun->send = slip_send;
if_tun->output = NULLFP;
if_tun->type = CL_NONE;
sprintf(tundevice,"/dev/tun%s",argv[3]);
if((pp->IOser = open(tundevice, O_RDWR)) == -1) {
tprintf("Can't open %s\n",tundevice);
free((char *)if_tun);
return -1;
}
/* Configure the tun device, binding it to the proper
underlying interface */
/* strncpy(ifr.ifr_name, argv[2], sizeof ifr.ifr_name);*/
/* Enable interrupt for input to an empty queue */
val = -getpid();
ioctl(pp->IOser,TIOCSPGRP,&val);
val = 1;
ioctl(pp->IOser,FIOASYNC,&val);
ioctl(pp->IOser,FIONBIO,&val); /* non-blocking mode */
/* Flush the read queue, to get rid of anything that accumulated
before the device reached its final configuration. */
/* ioctl(pp->IOser, I_FLUSH, (char *)FLUSHR);*/
if_tun->next = Ifaces;
Ifaces = if_tun;
newproc("tunnel_rx",2048,tun_input,0,(void *)pp,NULL,0);
tprintf("Attached %s\n",argv[2]);
++Ntun;
seteuid(getuid()); /* reset any SETUID privs we might have! KA9WSB */
return 0;
}
/* This is the task that takes care of incoming IP packets.
It would be better to do all this at interrupt level (ie from inpint)
but the program seems to crash if you do memory allocation operations
from interrupt level without using alloc.c
*/
void tun_input(unused,arg,unused2)
void *arg;
void *unused2;
{
int res;
struct mbuf *bp;
struct phdr *phdr;
char buf[TUNMTU], i_state;
struct tundrvr *pp;
pp = (struct tundrvr *) arg;
for (;;) {
/* If there are no new messages to fetch from the tun interface,
* then wait until inpint() gives you a signal.
*/
res = 0;
ioctl(pp->IOser,FIONREAD,&res); /* Find how much to read */
if(res == 0) {
i_state = dirps();
pwait(pp);
restore(i_state);
continue;
}
res = read(pp->IOser,buf,TUNMTU);
if (res == -1){
perror("read");
continue;
}
/* Process the packet. */
if((bp = alloc_mbuf(res+sizeof(struct phdr))) == NULLBUF){
tprintf(Nospace);
continue;
}
memcpy(bp->data+sizeof(struct phdr),buf,res);
/* Generate descriptor header */
phdr = (struct phdr *)bp->data;
phdr->iface = pp->iface;
phdr->type = CL_NONE;
bp->cnt = res + sizeof(struct phdr);
enqueue(&Hopper,bp);
}
}
/* Send raw packet (caller provides header) */
int
tun_raw(iface,bp)
struct iface *iface; /* Pointer to interface control block */
struct mbuf *bp; /* Data field */
{
register struct tundrvr *pp;
struct mbuf *bp1;
short size;
char i_state;
pp = &Tundrvr[iface->dev];
/* pp->stats.xmit++;*/
size = len_p(bp);
if(bp->next != NULLBUF){
/* Copy to contiguous buffer, since driver can't handle mbufs */
bp1 = copy_p(bp,size);
free_p(bp);
bp = bp1;
if(bp == NULLBUF)
return -1;
}
dump(iface,IF_TRACE_OUT,CL_NONE,bp);
i_state = dirps();
write(pp->IOser,bp->data,size);
restore(i_state);
free_p(bp);
return 0;
}
int
tun_stop()
{
}